import { cloneDeep, round } from 'lodash'
import useChartOptions from '@/common/hooks/chartOptions'

const { themeStyle } = useChartOptions()
export class CustomMarker {
  constructor(chart, xLabel = '') {
    this.chart = chart // 图表实例
    this.xLabelFormatter = xLabel.renderFormatter || xLabel.formatter // x 轴坐标数据处理函数
    this.marker = null // 标记点renderer定义 svg > path
    this.text = null // 右上文字定义
    this.point = null // 标记点定义 [ x, y ]
    this.index = [0, 0] // 坐标轴取值定义
    chart.customMarker = this // customMarker 实例反注册
  }
  markerPoint(target, axis) {
    const { series } = this.chart
    if (axis) {
      this.point = target
      this.index = [axis[0], target.index]
    } else {
      this.point = this.findClosestPoint(series, target)
    }
    this.drawCustomShape()
    this.drawAxisInfo(this.point)
  }
  drawCustomShape() {
    if (this.marker) {
      this.marker.destroy()
    }
    const x = this.point.plotX + this.chart.plotLeft
    const y = this.point.plotY + this.chart.plotTop
    var path = [] // 添加路径
    path.push('M', x, y) // 移动到起始点
    path.push('L', x + 6, y - 12) // 画一条线
    path.push('L', x - 6, y - 12) // 画一条线
    path.push('Z') // 关闭路径  // 将路径添加到图表中
    this.marker = this.chart.renderer
      .path(path)
      .attr({ stroke: '#000', 'stroke-width': 1, fill: '#fff', zIndex: 5 })
    this.marker.add()
  }
  drawAxisInfo(point) {
    if (this.text) {
      this.text.destroy()
    }
    const { chartWidth } = this.chart
    const yUnit = this.chart.userOptions.yAxis.unit || ''
    const textContent = `Mkr: ${this.xAxisFormatter(point.x)}, ${round(point.y, 2)}${yUnit}`
    const textWidth = this.getTextWidth(textContent)
    this.text = this.chart.renderer.text(textContent, chartWidth - textWidth - 48, 50).attr({
      zIndex: 5,
      fill: themeStyle.value.labelColor
    })
    this.text.add()
  }
  xAxisFormatter(val) {
    if (!this.xLabelFormatter) {
      return round(val, 2)
    }
    return this.xLabelFormatter.call({ value: round(val, 2), axis: this.chart.userOptions.xAxis })
  }
  getTextWidth(text) {
    const myspan = document.createElement('span')
    myspan.innerText = text
    document.body.append(myspan)
    const textWidth = myspan.getBoundingClientRect().width
    document.body.removeChild(myspan)
    return textWidth
  }
  getDistance(p1, p2, x = 0, y = 1) {
    const dx = p1[x] - p2[0]
    const dy = p1[y] - p2[1]
    return Math.sqrt(dx * dx + dy * dy)
  }
  getPoints(item) {
    const { points, data, xData, yData } = item
    if (points.length > 0) {
      return points
    } else if (data.length > 0) {
      return data
    } else {
      return xData.map((x, i) => [x, yData[i]])
    }
  }
  findClosestPoint(series, a) {
    let minDist = Infinity
    let closestPoint = null
    series.forEach((item, sInex) => {
      const points = this.getPoints(item)
      let len = points.length
      for (let i = 0; i < len; i++) {
        const p = points[i]
        const dist = this.getDistance(p, a, 'plotX', 'plotY')
        if (dist < minDist) {
          minDist = dist
          closestPoint = p
          this.index = [sInex, i]
        }
      }
    })
    return closestPoint
  }
  update() {
    if (!this.marker) {
      return
    }
    const { series } = this.chart
    const [sIndex, pIndex] = this.index
    this.point = series[sIndex].points[pIndex]
    if (!this.point) {
      return
    }
    this.drawCustomShape()
    this.drawAxisInfo(this.point)
  }
}
